// node 类型枚举
import { register } from '@antv/x6-vue-shape';
import { parseObj2Arr } from '@/utils/parseObj2Arr';
import StartNodeShape from '../component/custom-node-shape/start-node-shape.vue';
import RepositoryNodeShape from '../component/custom-node-shape/repository-node-shape.vue';
import ModelNodeShape from '../component/custom-node-shape/model-node-shape.vue';
import EndNodeShape from '../component/custom-node-shape/end-node-shape.vue';
import Chart from '../component/custom-node-shape/chart.vue';
import DataQuery from '../component/custom-node-shape/data-query.vue';
import QuestionClassifier from '../component/custom-node-shape/question-classifier.vue';
import ConditionalBranch from '../component/custom-node-shape/conditional-branch.vue';
import ParameterExtraction from '../component/custom-node-shape/parameter-extraction.vue';
import Code from '../component/custom-node-shape/code.vue';
import Qa from '../component/custom-node-shape/qa-node.vue';
import Tool from '../component/custom-node-shape/tool.vue';
import Iteration from '../component/custom-node-shape/iteration.vue';
import Report from '../component/custom-node-shape/report.vue';
import IterationBody from '../component/custom-node-shape/iteration-body.vue';
import {NodeTypeEnum} from '@/view/graph/model/type';

export enum NODES_MAP {
  // 开始
  START = 'start',
  // 知识库
  REPOSITORY = 'knowledge-retrieval',
  // 大模型
  MODEL = 'llm',
  // 结束
  END = 'end'
}

// 输入、输出
export enum PORT_ENUM {
  INPUT = 'input',
  OUTPUT = 'output',
  BOTTOM_INPUT = 'bottom-input',
  TOP_OUTPUT = 'top-output'
}
export const BODY_INPUT_PORT = {
  id: PORT_ENUM.INPUT,
  group: 'right'
};

export const BODY_OUTPUT_PORT = {
  id: PORT_ENUM.OUTPUT,
  group: 'left'
};

export const INPUT_PORT = {
  id: PORT_ENUM.INPUT,
  group: 'left'
};

export const OUTPUT_PORT = {
  id: PORT_ENUM.OUTPUT,
  group: 'right'
};

export const BOTTOM_PORT = {
  id: PORT_ENUM.BOTTOM_INPUT,
  group: 'bottom'
};

export const TOP_PORT = {
  id: PORT_ENUM.TOP_OUTPUT,
  group: 'top'
};

export const COMMON_LEFT_PORT = {
  left: {
    position: 'left',
    attrs: {
      circle: {
        magnet: true,
        stroke: '#fff',
        fill: '#22C899',
        r: 5
      }
    }
  }
};

export const COMMON_RIGHT_PORT = {
  right: {
    position: 'right',
    attrs: {
      circle: {
        magnet: true,
        stroke: '#fff',
        fill: '#22C899',
        r: 5
      }
    }
  }
};

export const COMMON_BOTTOM_PORT = {
  bottom: {
    position: 'bottom',
    attrs: {
      circle: {
        magnet: true,
        stroke: '#fff',
        fill: '#22C899',
        r: 5
      }
    }
  }
};

export const COMMON_TOP_PORT = {
  top: {
    position: 'top',
    attrs: {
      circle: {
        magnet: true,
        stroke: '#fff',
        fill: '#22C899',
        r: 5
      }
    }
  }
};

export const COMMON_ABSOLUTE_PORT = {
  right: {
    position: 'absolute',
    attrs: {
      circle: {
        magnet: true,
        stroke: '#fff',
        fill: '#22C899',
        r: 5
      }
    }
  }
};

const START_NODE_OPTION = {
  ports: {
    groups: {
      ...COMMON_RIGHT_PORT
    }
  },
  port: [OUTPUT_PORT],
  width: 160,
  height: 66,
  delIconPosition: { x: 80, y: 0 }
};

const END_NODE_OPTION = {
  ports: {
    groups: {
      ...COMMON_LEFT_PORT
    }
  },
  width: 160,
  height: 66,
  delIconPosition: { x: 80, y: 0 },
  port: [INPUT_PORT]
};

const BASIC_NODE_OPTION = {
  ports: {
    groups: {
      ...COMMON_LEFT_PORT,
      ...COMMON_RIGHT_PORT
    }
  },
  width: 160,
  height: 66,
  port: [OUTPUT_PORT, INPUT_PORT],
  delIconPosition: { x: 160, y: 4 }
};

const QUESTION_CLASS_NODE_OPTION = {
  ports: {
    groups: {
      ...COMMON_LEFT_PORT,
      ...COMMON_ABSOLUTE_PORT
    }
  },
  width: 160,
  height: 66,
  port: [OUTPUT_PORT, INPUT_PORT],
  delIconPosition: { x: 160, y: 4 }
};

const ITERATION_NODE_OPTION = {
  ports: {
    groups: {
      ...COMMON_LEFT_PORT,
      ...COMMON_RIGHT_PORT,
      ...COMMON_BOTTOM_PORT
    }
  },
  width: 160,
  height: 66,
  port: [OUTPUT_PORT, INPUT_PORT, BOTTOM_PORT],
  delIconPosition: { x: 160, y: 4 }
};

const ITERATION_BODY_NODE_OPTION = {
  ports: {
    groups: {
      ...COMMON_LEFT_PORT,
      ...COMMON_RIGHT_PORT,
      ...COMMON_TOP_PORT
    }
  },
  width: 536,
  height: 400,
  port: [TOP_PORT, BODY_OUTPUT_PORT, BODY_INPUT_PORT],
  delIconPosition: { x: 160, y: 4 }
};

interface NodeOptions {
  style?: any;
  port: any[];
  delIconPosition: { x: number; y: number };
  width?: number;
  height?: number;
  ports?: any;
}

export const NODE_MAP_OPTION: Record<NODES_MAP, NodeOptions> = {
  [NODES_MAP.START]: START_NODE_OPTION,
  [NODES_MAP.END]: END_NODE_OPTION,
  [NODES_MAP.MODEL]: BASIC_NODE_OPTION,
  [NODES_MAP.REPOSITORY]: BASIC_NODE_OPTION,
  [NodeTypeEnum.DATA_QUERY]: BASIC_NODE_OPTION,
  [NodeTypeEnum.CHAT]: BASIC_NODE_OPTION,
  [NodeTypeEnum.QUESTION_CLASS]: QUESTION_CLASS_NODE_OPTION,
  [NodeTypeEnum.CONDITIONAL_BRANCH]: QUESTION_CLASS_NODE_OPTION,
  [NodeTypeEnum.PARAMETER_EXTRACTION]: BASIC_NODE_OPTION,
  [NodeTypeEnum.CODE]: BASIC_NODE_OPTION,
  [NodeTypeEnum.QA]: QUESTION_CLASS_NODE_OPTION,
  [NodeTypeEnum.CUSTOM_TOOL]: BASIC_NODE_OPTION,
  [NodeTypeEnum.WORKFLOW_TOOL]: BASIC_NODE_OPTION,
  [NodeTypeEnum.REPORT]: BASIC_NODE_OPTION,
  [NodeTypeEnum.ITERATION]: ITERATION_NODE_OPTION,
  [NodeTypeEnum.ITERATION_BODY]: ITERATION_BODY_NODE_OPTION
};

export const registerNode = () => {
  const shapeItem = {
    [NODES_MAP.START]: StartNodeShape,
    [NODES_MAP.END]: EndNodeShape,
    [NODES_MAP.MODEL]: ModelNodeShape,
    [NODES_MAP.REPOSITORY]: RepositoryNodeShape,
    [NodeTypeEnum.DATA_QUERY]: DataQuery,
    [NodeTypeEnum.CHAT]: Chart,
    [NodeTypeEnum.QUESTION_CLASS]: QuestionClassifier,
    [NodeTypeEnum.CONDITIONAL_BRANCH]: ConditionalBranch,
    [NodeTypeEnum.PARAMETER_EXTRACTION]: ParameterExtraction,
    [NodeTypeEnum.CODE]: Code,
    [NodeTypeEnum.QA]: Qa,
    [NodeTypeEnum.CUSTOM_TOOL]: Tool,
    [NodeTypeEnum.WORKFLOW_TOOL]: Tool,
    [NodeTypeEnum.REPORT]: Report,
    [NodeTypeEnum.WORKFLOW_TOOL]: Tool,
    [NodeTypeEnum.ITERATION]: Iteration,
    [NodeTypeEnum.ITERATION_BODY]: IterationBody
  };
  // 注册节点
  const nodeList = parseObj2Arr(NODE_MAP_OPTION);
  nodeList.forEach(item => {
    const option = NODE_MAP_OPTION[item.key as NODES_MAP];
    register({
      shape: item.key,
      component: shapeItem[item.key as keyof typeof shapeItem],
      ...option
    });
  });
};

export const graphOption = {
  autoResize: true,
  panning: true,
  mousewheel: {
    enabled: true,
    modifiers: ['ctrl', 'meta']
  },
  background: {
    color: '#ffffff'
  },
  grid: {
    visible: true
    // type: 'doubleMesh',
    // args: [
    //   {
    //     color: '#eee', // 主网格线颜色
    //     thickness: 1 // 主网格线宽度
    //   },
    //   {
    //     color: '#ddd', // 次网格线颜色
    //     thickness: 1, // 次网格线宽度
    //     factor: 4 // 主次网格线间隔
    //   }
    // ]
  }
} as any;

export const edgeOption = {
  shape: 'edge',
  attrs: {
    line: {
      stroke: '#22C899',
      strokeWidth: 2
    }
  },
  router: {
    name: 'manhattan'
  },
  connector: {
    name: 'rounded',
    args: {
      radius: 10
    }
  }
};

export const HighlightingConfig = {
  magnetAvailable: {
    name: 'stroke',
    args: {
      attrs: {
        stroke: '#22C899',
        strokeWidth: 4
      }
    }
  },
  magnetAdsorbed: {
    name: 'stroke',
    args: {
      attrs: {
        stroke: '#22C899',
        strokeWidth: 4
      }
    }
  }
};

export function ValidateConnection(
  sourceCell: any,
  targetCell: any,
  sourceMagnet: any,
  targetMagnet: any
) {
  // 不能连接自身
  if (sourceCell === targetCell) {
    return false;
  }
  if (sourceCell.shape === NodeTypeEnum.ITERATION_BODY) {
    const children = sourceCell?.getChildren()?.map((item: any) => item.id);
    return !!(
      children?.includes(targetCell.id) && targetMagnet?.getAttribute('port-group') === 'left'
    );
  }
  if (targetCell.shape === NodeTypeEnum.ITERATION_BODY) {
    const children = targetCell?.getChildren()?.map((item: any) => item.id);
    return !!(
      children?.includes(sourceCell.id) && targetMagnet?.getAttribute('port-group') === 'right'
    );
  }
  if (!sourceMagnet || sourceMagnet.getAttribute('port-group') === 'left') {
    return false;
  }
  if (!targetMagnet || targetMagnet.getAttribute('port-group') !== 'left') {
    return false;
  }
  return true;
}
